package erfgame.core.xml;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;


import erfgame.core.CompassDirection;
import erfgame.core.DescribedValue;
import erfgame.core.entity.CompositeAssociation;
import erfgame.core.entity.Entity;
import erfgame.core.entity.EntityType;
import erfgame.core.entity.HasMaterialType;
import erfgame.core.entity.Orientable;
import erfgame.core.entity.Part;
import erfgame.core.entity.Physical;
import erfgame.core.entity.Stateful;
import erfgame.core.world.terrain.MaterialType;

public class BaseEntityPartXMLFactory implements ObjectXMLFactory<Entity> {
	
	public BaseEntityPartXMLFactory() {
		
	}

	public Element toXML(Entity entity, Document document) {
		Element result = document.createElement("part");
		if( entity != null ) {
			if( entity instanceof HasMaterialType ) {
				HasMaterialType hasMaterialType;
				hasMaterialType = (HasMaterialType)entity;
				MaterialType materialType = hasMaterialType.getMaterialType();
				// TODO need to serialize the entire material type (subclasses)
				result.setAttribute("material", clean(materialType.getName().getSingular()));
			}
//			if( entity instanceof Orientable ) {
//				Orientable orientable = (Orientable)entity;
//				CompassDirection direction = orientable.getOrientation();
//				if( direction != null ) {
//					result.setAttribute("orientation", direction.name());
//				}
//			}
	
			Node typeNode = toXML(entity.getEntityType(), document);
			result.appendChild(typeNode);
			
			if( entity instanceof Part ) {
				Part part = (Part)entity;
				Map<String, DescribedValue<Object>> descriptions = part.getDescriptions();
				if( descriptions != null ) {
					for( Map.Entry<String, DescribedValue<Object>> description : descriptions.entrySet() ) {
						Element descriptionElement = document.createElement("description");
						descriptionElement.setAttribute("key", description.getKey());
						DescribedValue<Object> value = description.getValue();
						descriptionElement.setAttribute("value", value.getValue().toString());
						descriptionElement.setTextContent(value.getDescription());
						result.appendChild(descriptionElement);
					}
				}
				List<CompositeAssociation> subparts = part.getAssociations();
				if( subparts != null ) {
					for( int i=subparts.size(); i>0; ) {
						i--;
						CompositeAssociation entry = subparts.get( i );
						Entity subPart = entry.getEntity();
						Element subPartNode = toXML(subPart, document);
					    // TODO turn to XML properly
						subPartNode.setAttribute("socket", clean(entry.getType().toString()));
						result.appendChild(subPartNode);
					}
				}
			} else if( entity instanceof Physical ) {
				Part body = ((Physical)entity).getBody();
				Element bodyNode = toXML(body, document);
				result.appendChild(bodyNode);
			}
		}		
		return result;
	}

	public Node toXML(EntityType type, Document document) {
		Element result = document.createElement("type");
		
		result.setAttribute("name", clean(type.getName().getSingular()));
		Collection<EntityType> parentTypes = type.getParentTypes();
		if( parentTypes != null ) {
    		for( EntityType parentType : parentTypes ) {
    			Node parentNode = toXML(parentType, document); 
    			result.appendChild(parentNode);
    		}
		}
		return result;
	}
	
	protected String clean(String s) {
	    return s.replace(' ', '-');
	}
}
